#pragma once

#include "../Shared/GObjHelpers.hpp"
#include "../Shared/TmpAllocator.hpp"
#include <glibmm.h>
#include "XmlppForward.hpp"

namespace BuildNG
{
  class InputFiles;
  class BuildContext;
    
  class InputFilesSet : public Object
  {
  public:
    class Group;
    class Iterator;
    friend class Iterator;

    InputFilesSet();
    ~InputFilesSet();

    static Glib::RefPtr<InputFilesSet> create();

    void                      clear();
    Glib::RefPtr<Group>       add_group();
    Glib::RefPtr<Group>       add_group_from_xml(const Xml::Element &xml);

    int                       get_num_input_files_entries() const;
    Glib::RefPtr<InputFiles>  get_input_files_entry(int i) const;
    Iterator                  get_input_files_entry_iterator();

    std::vector<Glib::ustring> build_physical_files(BuildContext &context);

    class Group : public Object
    {
      friend class Iterator;

    public:
      Group();
      virtual ~Group();

      Glib::RefPtr<Group>           add_child_group();
      Glib::RefPtr<Group>           add_child_group_from_xml(const Xml::Element &xml);

      void                          clear();
      int                           get_num_input_files_entries() const;

    private:
      Group(const Xml::Element &xml);

      std::vector<Glib::RefPtr<InputFiles> >  entries;
      std::vector<Glib::RefPtr<Group> >       child_groups;
    };

    class Iterator
    {
      friend class InputFilesSet;

    public:
      bool                      move_next();

      Glib::RefPtr<InputFiles>  get_entry();

    private:
      Iterator(Glib::RefPtr<InputFilesSet> files_set);

      Glib::RefPtr<InputFilesSet>       files_set;
      int                               index;

      Glib::RefPtr<InputFiles>          cur;

      struct RecursionStackEntry
      {
        Glib::RefPtr<Group> group;
        int index_in_parent;
      };
      TmpArray<RecursionStackEntry,16>  recursion_stack;
    };

  private:
    // a group, that's the parent of the groups added through 
    // the add_group, and add_group_from_xml functions.
    Glib::RefPtr<Group>                   root_group;
  };
}
